﻿using Common.Cache;
using Common.Tools;

namespace ChildService
{
    /// <summary>
    /// 自身信息推送
    /// </summary>
    public class SelfPush
    {
        /// <summary>
        ///  发送自身信息的定时器
        /// </summary>
        private readonly Timer _toSendTimer;
        /// <summary>
        /// 缓存使用
        /// </summary>
        private readonly ICustomCache _customCache;
        /// <summary>
        /// 构造函数
        /// </summary>
        public SelfPush(ICustomCache customCache)
        {
            _toSendTimer = new Timer(SendHandler, null, 1000, Timeout.Infinite);
            _customCache = customCache;
        }
        /// <summary>
        /// 定时发送自身信息
        /// </summary>
        /// <param name="state"></param>
        private async void SendHandler(object? state)
        {
            try
            {
                const string redisLock = "SelfLock";
                var lockToken = Guid.NewGuid().ToString(); //锁的令牌 
                var expiry = TimeSpan.FromSeconds(5); //过期时间 5s过期
                var self = await GetSelfDetail(); //获取自身信息
                var hostKey = $"{AppAddress.Instance.Ip}:{AppAddress.Instance.Port}";
                //获得锁，因为这个key所有子服务都要读取和修改，一次只允许一个来修改，所以需要加一个分布式锁
                if (await _customCache.LockTakeAsync(redisLock, lockToken, expiry))
                {
                    try
                    {
                        Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")} ********************************* 客户端 创建了锁 ********************************* ");
                        //获取子服务的信息
                        var dic = (await _customCache.GetAsync<Dictionary<string, SelfDetail>>(CommonConst.ChildDetailKey)) ?? new Dictionary<string, SelfDetail>();
                        if (dic.TryGetValue(hostKey, out var d))
                        {
                            d.TaskNum = self.TaskNum;
                            d.CpuInfo = self.CpuInfo;
                            d.MemeoryInfo = self.MemeoryInfo;
                            d.UpdateTime = self.UpdateTime;
                        }
                        else
                        {
                            dic.TryAdd(hostKey, self);
                        }
                        await _customCache.SetAsync(CommonConst.ChildDetailKey, dic, TimeSpan.FromMinutes(5));
                    }
                    catch (Exception ex)
                    {

                    }
                    finally
                    {
                        //释放锁
                        await _customCache.LockReleaseAsync(redisLock, lockToken);
                        Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")} ********************************* 客户端 释放了锁 ********************************* ");

                    }

                }

            }
            catch (Exception e)
            {
            }
            finally
            {
                _toSendTimer.Change(1000, Timeout.Infinite);
            }
        }
        /// <summary>
        /// 获取自身的信息
        /// </summary>
        /// <returns></returns>
        private async Task<SelfDetail> GetSelfDetail()
        {
            //获取任务数量
            var taskNum = await _customCache.GetAsync<long>($"{AppAddress.Instance.Ip}:{AppAddress.Instance.Port}");
            return new SelfDetail()
            {
                Ip = AppAddress.Instance.Ip,
                Port = AppAddress.Instance.Port,
                TaskNum = taskNum,
                CpuInfo = Convert.ToInt32(DateTime.Now.ToString("ff")),
                MemeoryInfo = Convert.ToInt32(DateTime.Now.ToString("ff")),
                UpdateTime = DateTime.Now,
            };
        }
    }
}
